package com.jack.webrtcsimple.signal

import android.util.Log
import org.java_websocket.client.WebSocketClient
import org.java_websocket.drafts.Draft_6455
import org.java_websocket.handshake.ServerHandshake
import org.json.JSONException
import org.json.JSONObject
import java.net.URI
import java.net.URISyntaxException

class RTCSignalClient(listener: OnSignalEventListener?) {
    private val mOnSignalEventListener: OnSignalEventListener?

    private var mWebSocketClient: WebSocketClient? = null
    var userId: String? = null
        private set
    private var mRoomId: String? = null


    init {
        var uri: URI? = null
        try {
            uri = URI(WS_URL)
        } catch (e: URISyntaxException) {
            e.printStackTrace()
        }
        mOnSignalEventListener = listener // 设置回调函数
        mWebSocketClient = JWebSocketClient(uri!!) // 新建websocket类
        mOnSignalEventListener!!.onConnecting() // 通知应用层正在连接信令服务器

        mWebSocketClient!!.connect() // 去连接信令服务器
        Log.i(TAG, "RTCSignalClient")
    }


    inner class JWebSocketClient(serverUri: URI) : WebSocketClient(serverUri, Draft_6455()) {
        override fun onOpen(handshakedata: ServerHandshake?) { // 说明websocket连接成功
            Log.i(TAG, "onOpen()")
            if (mOnSignalEventListener != null) {
                mOnSignalEventListener.onConnected()
            }
        }

        override fun onMessage(message: String) { // 接收服务器发送过来的数据
            Log.i(TAG, "onMessage()")
            if (mOnSignalEventListener != null) {
                try {
                    val jsonMsg = JSONObject(message)
                    val cmd = jsonMsg.getString("cmd")
                    when (cmd) {
                        SIGNAL_TYPE_NEW_PEER -> mOnSignalEventListener.onRemoteNewPeer(jsonMsg)
                        SIGNAL_TYPE_RESP_JOIN -> mOnSignalEventListener.onResponseJoin(jsonMsg)
                        SIGNAL_TYPE_PEER_LEAVE -> mOnSignalEventListener.onRemotePeerLeave(jsonMsg)
                        SIGNAL_TYPE_OFFER -> mOnSignalEventListener.onRemoteOffer(jsonMsg)
                        SIGNAL_TYPE_ANSWER -> mOnSignalEventListener.onRemoteAnswer(jsonMsg)
                        SIGNAL_TYPE_CANDIDATE -> mOnSignalEventListener.onRemoteCandidate(jsonMsg)
                        else -> Log.e(TAG, "can't handle the cmd " + cmd)
                    }
                } catch (e: JSONException) {
                    Log.e(TAG, "WebSocket message JSON parsing error: " + e.toString())
                }
            }
        }

        override fun onClose(code: Int, reason: String?, remote: Boolean) {
            Log.w(TAG, "onClose() reason:" + reason + ", clode:" + code)
            if (mOnSignalEventListener != null) {
                mOnSignalEventListener.onClosse()
            }
        }

        override fun onError(ex: Exception?) {
            Log.e(TAG, "onError()" + ex)
            if (mOnSignalEventListener != null) {
                mOnSignalEventListener.onDisconnected()
            }
        }
    }

    interface OnSignalEventListener {
        fun onConnected()
        fun onConnecting()
        fun onDisconnected()
        fun onClosse()
        fun onRemoteNewPeer(message: JSONObject?) // 新人加入
        fun onResponseJoin(message: JSONObject?) // 加入回应
        fun onRemotePeerLeave(message: JSONObject?)
        fun onRemoteOffer(message: JSONObject?)
        fun onRemoteAnswer(message: JSONObject?)
        fun onRemoteCandidate(message: JSONObject?)
    }

    fun joinRoom(userId: String?, roomId: String?) {
        Log.i(TAG, "joinRoom: " + userId + ", " + roomId)
        if (mWebSocketClient == null) {
            return
        }
        this.userId = userId
        mRoomId = roomId
        try {
            val args = JSONObject()
            args.put("cmd", SIGNAL_TYPE_JOIN)
            args.put("roomId", mRoomId)
            args.put("uid", this.userId)
            mWebSocketClient!!.send(args.toString())
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    fun leaveRoom() {
        Log.i(TAG, "leaveRoom: " + mRoomId)
        if (mWebSocketClient == null) {
            return
        }
        try {
            val args = JSONObject()
            args.put("cmd", SIGNAL_TYPE_LEAVE)
            args.put("roomId", mRoomId)
            args.put("uid", this.userId)
            mWebSocketClient!!.send(args.toString())
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    fun sendOffer(offer: String?, remoteUid: String?) {
        Log.i(TAG, "send offer")
        if (mWebSocketClient == null) {
            return
        }
        try {
            val args = JSONObject()
            args.put("cmd", SIGNAL_TYPE_OFFER)
            args.put("roomId", mRoomId)
            args.put("uid", this.userId)
            args.put("remoteUid", remoteUid)
            args.put("msg", offer)
            mWebSocketClient!!.send(args.toString())
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    fun sendAnswer(answer: String?, remoteUid: String?) {
        Log.i(TAG, "send answer")
        if (mWebSocketClient == null) {
            return
        }
        try {
            val args = JSONObject()
            args.put("cmd", SIGNAL_TYPE_ANSWER)
            args.put("roomId", mRoomId)
            args.put("uid", this.userId)
            args.put("remoteUid", remoteUid)
            args.put("msg", answer)
            mWebSocketClient!!.send(args.toString())
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    fun sendCandidate(candidate: String?, remoteUid: String?) {
        Log.i(TAG, "send candidate")
        if (mWebSocketClient == null) {
            return
        }
        try {
            val args = JSONObject()
            args.put("cmd", SIGNAL_TYPE_CANDIDATE)
            args.put("roomId", mRoomId)
            args.put("uid", this.userId)
            args.put("remoteUid", remoteUid)
            args.put("msg", candidate)
            mWebSocketClient!!.send(args.toString())
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }

    fun disConnect() {
        if (mWebSocketClient == null) {
            return
        }
        mWebSocketClient!!.close()
        mWebSocketClient = null
    }

    companion object {
        private const val TAG = "RTCSignalClient"

        private const val WS_URL = "ws://192.168.1.5:8099" //本地测试环境

        // join 主动加入房间
        // leave 主动离开房间
        // new-peer 有人加入房间，通知已经在房间的人
        // peer-leave 有人离开房间，通知已经在房间的人
        // offer 发送offer给对端peer
        // answer发送offer给对端peer
        // candidate 发送candidate给对端peer
        const val SIGNAL_TYPE_JOIN: String = "join"
        const val SIGNAL_TYPE_RESP_JOIN: String = "resp-join" // 告知加入者对方是谁
        const val SIGNAL_TYPE_LEAVE: String = "leave"
        const val SIGNAL_TYPE_NEW_PEER: String = "new-peer"
        const val SIGNAL_TYPE_PEER_LEAVE: String = "peer-leave"
        const val SIGNAL_TYPE_OFFER: String = "offer"
        const val SIGNAL_TYPE_ANSWER: String = "answer"
        const val SIGNAL_TYPE_CANDIDATE: String = "candidate"
    }
}
